package com.google.code.yargon.ui.component;

import java.util.HashMap;
import java.util.LinkedList;

/**
 * Non-buffered UI component. Each child class must implement method render() that does all the drawing what the component
 * needs to show on the screen. Scene is drawn directly to screen without buffering via ComponentManager. Each child class must also implement 
 * onClick(String id) which listens for mouse inputs. ComponentManager will call this method with given mouse hotspot id, defined with 
 * components addHotspot() method. 
 * 
 * @author Mika Myllynen
 *
 */
public abstract class Component {
	
	private int x;
	private int y;
	private int w;
	private int h;
	
	private float alpha;
	
	private boolean isClicked;
	private boolean isMoving;
	private boolean isMovable;
	private boolean isUpdated;
	
	// Coordinates where mouse button went down in this component, relative to components x,y
	private int mx;
	private int my;
	
	// Where scrolling should be limited
	protected int st;
	protected int sl;
	protected int sb;
	protected int sr;
	
	private HashMap<String, Hotspot> hotspots;
	private LinkedList<Component> tiedComponents;
	
	public Component(int x, int y, int w, int h, float alpha) {
		this.x = x;
		this.y = y;
		this.w = w;
		this.h = h;
		
		this.alpha = alpha;
		
		this.st = 0;
		this.sl = 0;
		this.sb = 0;
		this.sr = 0;
		
		this.isClicked = false;
		this.isMoving = false;
		this.isMovable = false;	
		this.isUpdated = false;
		
		this.hotspots = new HashMap<String, Hotspot>();
		this.tiedComponents = new LinkedList<Component>();
	}
	
	protected void setX(int x) {
		this.x = x;
		
		// Update tied components as well
		for(Component c : tiedComponents) {
			c.setX(x);
		}
	}

	protected void setY(int y) {
		this.y = y;
		
		// Update tied components as well
		for(Component c : tiedComponents) {
			c.setY(y);
		}
	}
	
	protected void setWidth(int w) {
		this.w = w;
	}
	
	protected void setHeight(int h) {
		this.h = h;
	}
		
	protected int getX() {
		return this.x;
	}

	protected int getY() {
		return this.y;
	}
	
	protected int getWidth() {
		return this.w;
	}

	protected int getHeight() {
		return this.h;
	}
	
	protected void setMouseDownX(int x) {
		this.mx = x;
	}

	protected void setMouseDownY(int y) {
		this.my = y;
	}
	
	protected int getMouseDownX() {
		return this.mx;
	}

	protected int getMouseDownY() {
		return this.my;
	}
	
	protected void setAlpha(float alpha) {
		this.alpha = alpha;
	}
	
	protected float getAlpha() {
		return this.alpha;
	}
	
	protected void setClicked(boolean c) {
		this.isClicked = c;
	}
	
	protected boolean isClicked() {
		return this.isClicked;
	}
	
	protected void setMoving(boolean m) {
		this.isMoving = m;
	}
	
	protected boolean isMoving() {
		return this.isMoving;
	}
	
	public void setMovable(boolean m) {
		this.isMovable = m;
	}
	
	protected boolean isMovable() {
		return this.isMovable;
	}
	
	public void setUpdated(boolean u) {
		this.isUpdated = u;
	}
	
	protected boolean isUpdated() {
		return this.isUpdated;
	}
	
	public void setMoveLimits(int left, int bottom, int right, int top) {
		this.sl = left;
		this.sb = bottom;
		this.sr = right;
		this.st = top;
	}
			
	/**
	 * Display component on screen at the currently defined location
	 * 
	 */
	protected void display() {
		render();
	}
	
	/**
	 * Add a mouse hot spot
	 * 
	 * @param id
	 * @param x
	 * @param y
	 * @param w
	 * @param h
	 */
	public void addHotspot(String id, int x, int y, int w, int h) {
		Hotspot hs = new Hotspot(x, y, w, h);
		hotspots.put(id, hs);
	}
	
	/** 
	 * Return all mouse hot spots
	 * 
	 * @return
	 */
	protected HashMap<String, Hotspot> getHotspots() {
		return hotspots;	
	}
	
	/** 
	 * Add a tied component to this component. Tied component moves when this component is moved.
	 *
	 * @param c component to tie
	 */
	public void tie(Component c) {
		tiedComponents.add(c);
	}
	
	/**
	 * Return all tied components
	 * 
	 * @return
	 */
	protected LinkedList<Component> getTiedComponents() {
		return tiedComponents;
	}
		
	protected class Hotspot {
		
		private int x;
		private int y;
		private int w;
		private int h;
		private boolean active;
		
		private Hotspot(int x, int y, int w, int h) {
			this.x = x;
			this.y = y;
			this.w = w;
			this.h = h;
			this.active = false;
		}
		
		protected int getX() {
			return this.x;
		}
		
		protected int getY() {
			return this.y;
		}
		
		protected int getW() {
			return this.w;
		}

		protected int getH() {
			return this.h;
		}
		
		protected boolean getActive() {
			return this.active;
		}
		
		protected void setActive(boolean active) {
			this.active = active;
		}
	}
	
	/**
	 * This reacts to mouse clicks. Each child component must implement this according to their needs.
	 * 
	 * @param id
	 */
	protected abstract void onClick(String id);
	
	/**
	 * This is where the drawing happens. Each child component must implement this according to their needs.
	 * 
	 */
	protected abstract void render();
	
	/**
	 * 
	 * 
	 */
	protected abstract void update();
}
